/*************************************************************************
	> File Name: FileHandler.hpp
	> Author: H.M. Lau
	> Mail: hm.lau@outlook.com
	> Created Time: 2023/10/06 18:11
 ************************************************************************/

#pragma once

#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <fstream>
#include <cerrno>
#include "log.hpp"

const int LINE_SIZE = 256;

class FileHandler
{
public:
    FileHandler () : _curPos(0) {}

    void open(const std::string& filename = "")
    {
        if (filename.empty()) _readIn(std::cin);
        else {
            std::ifstream input(filename);
            if (!input.is_open()) {
                log::logMessage(log::LOG_LEVEL::_FATAL, "file open error, %d:%s", errno, strerror(errno));
                exit(1);
            }
            _readIn(input);
            input.close();
        }

        if (filename.empty()) log::logMessage(log::LOG_LEVEL::_INFO, "read stdin success.");
        else log::logMessage(log::LOG_LEVEL::_INFO, "read file: %s success.", filename.c_str());
    }

    std::string read() const
    { return _input_buffer; }

    int read(char* buf, const size_t begin, const size_t len) const
    {
        size_t readCnt = 0;
        for (; _curPos + readCnt < _input_buffer.size() && readCnt < len; ++readCnt) buf[begin + readCnt] = _input_buffer[_curPos + readCnt];
        return readCnt;
    }

    std::string getBuffer() const
    { return _input_buffer; }

    void clear()
    {
        FileHandler temp;
        std::swap(*this, temp);
    }

private:
    void _readIn(std::istream& input)
    {
        std::string line;
        while (std::getline(input, line)) {
            if (line == "end")  break;
            _input_buffer += line.c_str();
            _input_buffer += '\n';
        }
    }

    std::string _input_buffer;
    size_t _curPos;
};
